package xyz.labmem.app.dialog.form

import atlantafx.base.theme.Styles
import cn.hutool.core.convert.Convert
import cn.hutool.core.util.StrUtil
import javafx.event.EventHandler
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.control.PasswordField
import javafx.scene.control.TextArea
import javafx.scene.control.TextField
import javafx.scene.layout.HBox
import javafx.scene.layout.Region
import javafx.scene.layout.VBox
import javafx.scene.paint.Color
import xyz.labmem.app.config.AppConfig.mouseImage
import xyz.labmem.app.dialog.DialogBtn
import xyz.labmem.app.dialog.FormDialog
import xyz.labmem.app.dialog.FormInterFace
import xyz.labmem.app.main.MainStage
import xyz.labmem.app.unit.LabelUnit
import xyz.labmem.app.unit.MsgUnit
import xyz.labmem.app.unit.ProxyListUnit
import xyz.labmem.app.unit.SwitchUnit
import xyz.labmem.lipx.core.context.AppContext.Client.makeId
import xyz.labmem.lipx.core.entity.ClientConfig
import xyz.labmem.lipx.core.util.ClientConfigDataUtil
import xyz.labmem.util.viewRun
import java.util.HashSet

/**
 * @author       : ltty
 * @description  :
 * @createDate   : 2024/10/16
 */
class ClientConfigForm(override val title: String, private val cc: ClientConfig) : FormInterFace {
    override val intoForm = ArrayList<Region>()
    override val intoBtns = ArrayList<DialogBtn>()
    override val formWidth = 620.0
    override val formHeight = 400.0
    override val alignment = Pos.CENTER_RIGHT
    override var closeForm: (() -> Unit)? = null

    private val group = TextField(cc.group)
    private val name = TextField(cc.remark)
    private val serverHost = TextField(cc.serverHost)
    private val serverPort = TextField(cc.serverPort?.toString())
    private val proxyHost = TextField(cc.proxyHost)
    private val proxyPort = TextField(cc.proxyPort?.toString())
    private val targetPort = TextField(cc.targetPort?.toString())
    private val password = PasswordField()
    private val wls = TextArea(cc.wls.joinToString(","))
    private val auto = SwitchUnit(cc.autoRun)
    private val msg = MsgUnit.getMsgUnit()

    init {
        makeItem("分组", group)
        makeItem("名称", name)
        makeItem("服务器地址", serverHost)
        makeItem("服务器端口", serverPort)
        makeItem("代理地址", proxyHost)
        makeItem("代理端口", proxyPort)
        makeItem("目标端口", targetPort)
        password.text = cc.password
        makeItem("密码", password)
        wls.prefWidth = 230.0
        wls.prefRowCount = 3
        makeItem("白名单", wls)
        makeItem("自启动", auto)
        DialogBtn("确定", color = Color.web("#ffed07")) {
            verify()
        }.apply {
            VBox.setMargin(this, Insets(0.0, 5.0, 20.0, 0.0))
            intoBtns.add(this)
        }
    }

    private fun makeItem(label: String, input: Region) {
        if (input !is SwitchUnit) {
            input.cursor = mouseImage["m5"]
            input.onMouseEntered = EventHandler {
                MainStage.setCursor(mouseImage["m5"])
                FormDialog.setCursor(mouseImage["m5"])
            }
            input.onMouseExited = EventHandler {
                MainStage.cursorBack()
                FormDialog.cursorBack()
            }
            HBox.setMargin(input, Insets(.0, .0, .0, 20.0))
        } else {
            HBox.setMargin(input, Insets(.0, 130.0, .0, 20.0))
        }
        intoForm.add(HBox(LabelUnit(label, 22.0, rotateE = 5.0, rotateS = -5.0), input).apply {
            VBox.setMargin(this, Insets(10.0, 10.0, .0, .0))
            alignment = Pos.CENTER_RIGHT
        })
    }

    //校验
    private fun verify() {
        listOf(group, name, serverHost, serverPort, proxyHost, proxyPort, targetPort, password, wls).forEach {
            it.pseudoClassStateChanged(Styles.STATE_DANGER, false)
        }
        //分组
        if (notNull(listOf(group, name, serverHost, serverPort, proxyHost, proxyPort, targetPort))) {
            if (group.text.length > 64) {
                msg.showMsg("分组 字符长度不能超过64 喵~")
                group.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            if (name.text.length > 64) {
                msg.showMsg("名称 字符长度不能超过64 喵~")
                name.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            if (serverHost.text.length > 128) {
                msg.showMsg("服务地址 字符长度不能超过64 喵~")
                serverHost.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            try {
                Convert.toInt(serverPort.text)
                if (serverPort.text.toInt() <= 0 || serverPort.text.toInt() > 65535) {
                    msg.showMsg("服务端口 必须为1-65535 喵~")
                    serverPort.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                    return
                }
            } catch (e: Exception) {
                msg.showMsg("服务端口 必须为正整数 喵~")
                serverPort.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            if (proxyHost.text.length > 128) {
                msg.showMsg("代理地址 字符长度不能超过64 喵~")
                proxyHost.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            try {
                Convert.toInt(proxyPort.text)
                if (proxyPort.text.toInt() <= 0 || proxyPort.text.toInt() > 65535) {
                    msg.showMsg("代理端口 必须为1-65535 喵~")
                    proxyPort.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                    return
                }
            } catch (e: Exception) {
                msg.showMsg("代理端口 必须为正整数 喵~")
                proxyPort.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            try {
                Convert.toInt(targetPort.text)
                if (targetPort.text.toInt() <= 0 || targetPort.text.toInt() > 65535) {
                    msg.showMsg("转发端口 必须为1-65535 喵~")
                    targetPort.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                    return
                }
            } catch (e: Exception) {
                msg.showMsg("转发端口 必须为正整数 喵~")
                targetPort.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            if (StrUtil.isNotBlank(password.text) && (password.text.length < 4 || password.text.length > 32)) {
                msg.showMsg("密码 字符长度需在4-32位 喵~")
                password.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                return
            }
            if (StrUtil.isNotBlank(wls.text)) {
                if (wls.text.length > 255) {
                    msg.showMsg("白名单 字符长度不能超过255 喵~")
                    wls.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                    return
                }
                try {
                    HashSet(wls.text.split(","))
                } catch (i: Exception) {
                    msg.showMsg("白名单 数组输入错误！示例: 127.0.0.1,127.0.0.2 喵~")
                    wls.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                    return
                }
            }
            save()
        }
    }

    private fun notNull(item: List<TextField>): Boolean {
        var v = true
        item.forEach {
            if (StrUtil.isBlank(it.text)) {
                it.pseudoClassStateChanged(Styles.STATE_DANGER, true)
                v = false
            }
        }
        if (!v)
            msg.showMsg("这些字段不能为空 请正确填写 喵~")
        return v
    }

    private fun save() {
        MainStage.loadingView {
            try {
                cc.group = group.text
                cc.remark = name.text
                cc.serverHost = serverHost.text
                cc.serverPort = serverPort.text.toInt()
                cc.proxyHost = proxyHost.text
                cc.proxyPort = proxyPort.text.toInt()
                cc.targetPort = targetPort.text.toInt()
                cc.autoRun = auto.valueProperty.value
                if (StrUtil.isBlank(cc.id)) {
                    cc.id = makeId()
                }
                cc.password = password.text
                cc.wls = if (StrUtil.isNotBlank(wls.text)) HashSet(wls.text.split(",")) else HashSet()
                ClientConfigDataUtil.write(cc)
                msg.showMsg("${cc.type!!.getCN()} ${cc.remark} 保存成功了喵~")
                viewRun {
                    ProxyListUnit.refresh()
                }
                closeForm?.let { it() }
            } catch (e: Exception) {
                msg.showMsg("保存失败了喵~")
            }
        }
    }

}